home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 51 / Amiga Format CD51 (2000-03-10)(Future Publishing)(GB)[!][issue 2000-04].iso / -in_the_mag- / workbench / term_4.8 / extras / source / term-source.lha / Translate.c < prev    next >
C/C++ Source or Header  |  1997-10-03  |  20KB  |  1,094 lines

  1. /*
  2. **    Translate.c
  3. **
  4. **    Character translation support routines
  5. **
  6. **    Copyright © 1990-1997 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Translation chunk header types. */
  17.  
  18. enum    {    TYPE_NONE, TYPE_SEND, TYPE_RECEIVE };
  19.  
  20.     /* Master translation table entry types. */
  21.  
  22. enum    {    TRANSLATION_VERBATIM, TRANSLATION_IGNORE, TRANSLATION_OTHER };
  23.  
  24.     /* Symbolic names for character codes. */
  25.  
  26. STATIC struct { STRPTR Name; UBYTE Value; } CodeTab[] =
  27. {
  28.     {    "NUL",    0    },
  29.     {    "SOH",    1    },
  30.     {    "STX",    2    },
  31.     {    "ETX",    3    },
  32.     {    "EOT",    4    },
  33.     {    "ENQ",    5    },
  34.     {    "ACK",    6    },
  35.     {    "BEL",    7    },
  36.     {    "BS",    8    },
  37.     {    "HT",    9    },
  38.     {    "LF",    10    },
  39.     {    "VT",    11    },
  40.     {    "FF",    12    },
  41.     {    "CR",    13    },
  42.     {    "SO",    14    },
  43.     {    "SI",    15    },
  44.     {    "DLE",    16    },
  45.     {    "DC1",    17    },
  46.     {    "DC2",    18    },
  47.     {    "DC3",    19    },
  48.     {    "DC4",    20    },
  49.     {    "NAK",    21    },
  50.     {    "SYN",    22    },
  51.     {    "ETB",    23    },
  52.     {    "CAN",    24    },
  53.     {    "EM",    25    },
  54.     {    "SUB",    26    },
  55.     {    "ESC",    27    },
  56.     {    "FS",    28    },
  57.     {    "GS",    29    },
  58.     {    "RS",    30    },
  59.     {    "US",    31    },
  60.     {    "SP",    32    },
  61.     {    "DEL",    127    },
  62.     {    "SS2",    142    },
  63.     {    "SS3",    143    },
  64.     {    "DCS",    144    },
  65.     {    "CSI",    155    },
  66.     {    "ST",    156    },
  67.     {    "OSC",    157    },
  68.     {    "PM",    158    },
  69.     {    "APC",    159    },
  70.     {    "NBS",    160    },
  71.     {    "SHY",    173    }
  72. };
  73.  
  74.     /* TranslateSetup():
  75.      *
  76.      *    Set up for buffer translation.
  77.      */
  78.  
  79. VOID
  80. TranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  81. {
  82.     Handle->LocalBuffer            = NULL;
  83.     Handle->LocalLen            = 0;
  84.  
  85.     Handle->SourceBuffer        = SourceBuffer;
  86.     Handle->SourceLen            = SourceLen;
  87.  
  88.     Handle->DestinationBuffer    = DestinationBuffer;
  89.     Handle->DestinationLen        = DestinationLen;
  90.  
  91.     Handle->Table                = Table;
  92. }
  93.  
  94.     /* TranslateBuffer(struct TranslationHandle *Handle):
  95.      *
  96.      *    Translate buffer contents according to
  97.      *    translation table contents.
  98.      */
  99.  
  100. LONG
  101. TranslateBuffer(struct TranslationHandle *Handle)
  102. {
  103.     struct TranslationEntry    *Entry;
  104.     LONG BytesWritten;
  105.     STRPTR Data;
  106.  
  107.     Data = Handle->DestinationBuffer;
  108.     BytesWritten = 0;
  109.  
  110.         /* Are we to return any translated data? */
  111.  
  112.     while(Handle->LocalLen && BytesWritten < Handle->DestinationLen)
  113.     {
  114.             /* Decrement number of bytes in buffer. */
  115.  
  116.         Handle->LocalLen--;
  117.  
  118.             /* Return next character. */
  119.  
  120.         *Data++ = *Handle->LocalBuffer++;
  121.  
  122.             /* Add another byte. */
  123.  
  124.         BytesWritten++;
  125.     }
  126.  
  127.         /* Loop until done. */
  128.  
  129.     while(Handle->SourceLen && BytesWritten < Handle->DestinationLen)
  130.     {
  131.             /* Another byte eaten. */
  132.  
  133.         Handle->SourceLen--;
  134.  
  135.             /* Get table entry. */
  136.  
  137.         if(Entry = Handle->Table[*Handle->SourceBuffer++])
  138.         {
  139.                 /* Copy to local data area. */
  140.  
  141.             Handle->LocalBuffer    = Entry->String;
  142.             Handle->LocalLen    = Entry->Len;
  143.  
  144.                 /* Translate the data. */
  145.  
  146.             while(Handle->LocalLen && BytesWritten < Handle->DestinationLen)
  147.             {
  148.                     /* Decrement number of bytes in buffer. */
  149.  
  150.                 Handle->LocalLen--;
  151.  
  152.                     /* Return next character. */
  153.  
  154.                 *Data++ = *Handle->LocalBuffer++;
  155.  
  156.                     /* Add another byte. */
  157.  
  158.                 BytesWritten++;
  159.             }
  160.         }
  161.     }
  162.  
  163.     return(BytesWritten);
  164. }
  165.  
  166.     /* NameToCode(STRPTR Name):
  167.      *
  168.      *    Translate a symbolic character code name of numeral.
  169.      */
  170.  
  171. UBYTE
  172. NameToCode(STRPTR Name)
  173. {
  174.     LONG i;
  175.  
  176.     for(i = 0 ; i < NUM_ELEMENTS(CodeTab) ; i++)
  177.     {
  178.         if(!Stricmp(CodeTab[i].Name,Name))
  179.             return(CodeTab[i].Value);
  180.     }
  181.  
  182.     return((UBYTE)Atol(Name));
  183. }
  184.  
  185.     /* CodeToName(UBYTE Code):
  186.      *
  187.      *    Translate a character code into a symbolic
  188.      *    name or numeral.
  189.      */
  190.  
  191. STRPTR
  192. CodeToName(UBYTE Code)
  193. {
  194.     STATIC UBYTE Name[6];
  195.  
  196.     LONG i;
  197.  
  198.     for(i = 0 ; i < NUM_ELEMENTS(CodeTab) ; i++)
  199.     {
  200.         if(CodeTab[i].Value == Code)
  201.             return(CodeTab[i].Name);
  202.     }
  203.  
  204.     LimitedSPrintf(sizeof(Name),Name,"%03ld",Code);
  205.  
  206.     return(Name);
  207. }
  208.  
  209.     /* FreeTranslationTable(struct TranslationEntry **Table):
  210.      *
  211.      *    Free a character translation table.
  212.      */
  213.  
  214. VOID
  215. FreeTranslationTable(struct TranslationEntry **Table)
  216. {
  217.     LONG i;
  218.  
  219.     for(i = 0 ; i < 256 ; i++)
  220.     {
  221.         if(Table[i])
  222.             FreeTranslationEntry(Table[i]);
  223.     }
  224.  
  225.     FreeVecPooled(Table);
  226. }
  227.  
  228.     /* AllocTranslationTable():
  229.      *
  230.      *    Allocate a character translation table.
  231.      */
  232.  
  233. struct TranslationEntry **
  234. AllocTranslationTable()
  235. {
  236.     return((struct TranslationEntry **)AllocVecPooled(sizeof(struct TranslationEntry *) * 256,MEMF_ANY|MEMF_CLEAR));
  237. }
  238.  
  239.     /* FreeTranslationEntry(struct TranslationEntry *Entry):
  240.      *
  241.      *    Free a character translation table entry.
  242.      */
  243.  
  244. VOID
  245. FreeTranslationEntry(struct TranslationEntry *Entry)
  246. {
  247.     FreeVecPooled(Entry);
  248. }
  249.  
  250.     /* TranslateString(STRPTR From,STRPTR To):
  251.      *
  252.      *    Translate a string to contain control codes
  253.      *    into a string to contain the real codes.
  254.      */
  255.  
  256. LONG
  257. TranslateString(STRPTR From,STRPTR To)
  258. {
  259.     BOOL GotControl,GotEscape;
  260.     LONG Len,Count,i;
  261.  
  262.     GotControl    = FALSE;
  263.     GotEscape    = FALSE;
  264.  
  265.     Len        = strlen(From);
  266.     Count    = 0;
  267.  
  268.     for(i = 0 ; i < Len ; i++)
  269.     {
  270.         if(!GotControl && !GotEscape)
  271.         {
  272.             if(From[i] == '\\')
  273.             {
  274.                 GotControl = TRUE;
  275.  
  276.                 continue;
  277.             }
  278.  
  279.             if(From[i] == '^')
  280.             {
  281.                 GotEscape = TRUE;
  282.  
  283.                 continue;
  284.             }
  285.  
  286.             To[Count++] = From[i];
  287.         }
  288.         else
  289.         {
  290.             if(GotEscape)
  291.             {
  292.                 if(ToUpper(From[i]) >= 'A' && ToUpper(From[i]) <= '_')
  293.                     To[Count++] = ToUpper(From[i]) - '@';
  294.                 else
  295.                     To[Count++] = From[i];
  296.  
  297.                 GotEscape = FALSE;
  298.             }
  299.             else
  300.             {
  301.                 if(GotControl)
  302.                 {
  303.                     switch(ToUpper(From[i]))
  304.                     {
  305.                             /* These macro commands are plainly
  306.                              * ignored.
  307.                              */
  308.  
  309.                         case '0':
  310.                         case '1':
  311.                         case '2':
  312.                         case '3':
  313.                         case '4':
  314.                         case '5':
  315.                         case '6':
  316.  
  317.                             break;
  318.  
  319.                             /* These are macro commands and
  320.                              * not supported.
  321.                              */
  322.  
  323.                         case 'A':
  324.                         case 'C':
  325.                         case 'D':
  326.                         case 'G':
  327.                         case 'H':
  328.                         case 'I':
  329.                         case 'P':
  330.                         case 'U':
  331.                         case 'X':
  332.  
  333.                             To[Count++] = '\\';
  334.                             To[Count++] = From[i];
  335.                             break;
  336.  
  337.                             /* Translate code. */
  338.  
  339.                         case '*':
  340.  
  341.                             i++;
  342.  
  343.                             while(i < Len && From[i] == ' ')
  344.                                 i++;
  345.  
  346.                             if(i < Len)
  347.                             {
  348.                                 UBYTE DummyBuffer[5],j = 0,Char;
  349.  
  350.                                 if(From[i] >= '0' && From[i] <= '9')
  351.                                 {
  352.                                     while(j < 3 && i < Len)
  353.                                     {
  354.                                         Char = From[i++];
  355.  
  356.                                         if(Char >= '0' && Char <= '9')
  357.                                             DummyBuffer[j++] = Char;
  358.                                         else
  359.                                         {
  360.                                             i--;
  361.  
  362.                                             break;
  363.                                         }
  364.                                     }
  365.                                 }
  366.                                 else
  367.                                 {
  368.                                     while(j < 4 && i < Len)
  369.                                     {
  370.                                         Char = ToLower(From[i++]);
  371.  
  372.                                         if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  373.                                             DummyBuffer[j++] = Char;
  374.                                         else
  375.                                         {
  376.                                             i--;
  377.  
  378.                                             break;
  379.                                         }
  380.                                     }
  381.                                 }
  382.  
  383.                                 DummyBuffer[j] = 0;
  384.  
  385.                                 To[Count++] = NameToCode(DummyBuffer);
  386.                             }
  387.  
  388.                             i--;
  389.  
  390.                             break;
  391.  
  392.                             /* This is a backspace. */
  393.  
  394.                         case 'B':
  395.  
  396.                             To[Count++] = '\b';
  397.                             break;
  398.  
  399.                             /* This is a form feed. */
  400.  
  401.                         case 'F':
  402.  
  403.                             To[Count++] = '\f';
  404.                             break;
  405.  
  406.                             /* This is a line feed. */
  407.  
  408.                         case 'N':
  409.  
  410.                             To[Count++] = '\n';
  411.                             break;
  412.  
  413.                             /* This is a carriage return. */
  414.  
  415.                         case 'R':
  416.  
  417.                             To[Count++] = '\r';
  418.                             break;
  419.  
  420.                             /* This is a tab. */
  421.  
  422.                         case 'T':
  423.  
  424.                             To[Count++] = '\t';
  425.                             break;
  426.  
  427.                             /* Produce the escape character. */
  428.  
  429.                         case 'E':
  430.  
  431.                             To[Count++] = ESC;
  432.                             break;
  433.  
  434.                             /* Stuff the character into the buffer. */
  435.  
  436.                         default:
  437.  
  438.                             To[Count++] = From[i];
  439.                             break;
  440.                     }
  441.  
  442.                     GotControl = FALSE;
  443.                 }
  444.             }
  445.         }
  446.     }
  447.  
  448.     return(Count);
  449. }
  450.  
  451.     /* AllocTranslationEntry(STRPTR String):
  452.      *
  453.      *    Allocate a character translation table entry.
  454.      */
  455.  
  456. struct TranslationEntry *
  457. AllocTranslationEntry(STRPTR String)
  458. {
  459.     UBYTE LocalBuffer[256];
  460.     LONG Count;
  461.  
  462.     Count = TranslateString(String,LocalBuffer);
  463.  
  464.     if(Count > 0)
  465.     {
  466.         struct TranslationEntry *Entry;
  467.         UBYTE Type;
  468.  
  469.         if(Count > 1)
  470.         {
  471.             Type = TRANSLATE_STRING;
  472.  
  473.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Count + 1,MEMF_ANY|MEMF_CLEAR))
  474.             {
  475.                 Entry->String = (STRPTR)(Entry + 1);
  476.  
  477.                 CopyMem(LocalBuffer,Entry->String,Count);
  478.             }
  479.         }
  480.         else
  481.         {
  482.             Type = TRANSLATE_SINGLE;
  483.  
  484.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  485.             {
  486.                 Entry->String    = &Entry->Extra;
  487.                 Entry->Extra    = LocalBuffer[0];
  488.             }
  489.         }
  490.  
  491.         if(Entry)
  492.         {
  493.             Entry->Type    = Type;
  494.             Entry->Len    = Count;
  495.  
  496.             return(Entry);
  497.         }
  498.     }
  499.  
  500.     return(NULL);
  501. }
  502.  
  503.     /* FillTranslationTable(struct TranslationEntry **Table):
  504.      *
  505.      *    Fill the translation table with defaults.
  506.      */
  507.  
  508. BOOL
  509. FillTranslationTable(struct TranslationEntry **Table)
  510. {
  511.     BOOL Success;
  512.     LONG i;
  513.  
  514.     Success = TRUE;
  515.  
  516.     for(i = 0 ; Success && i < 256 ; i++)
  517.     {
  518.         if(Table[i] = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  519.         {
  520.             Table[i]->Type        = TRANSLATE_SINGLE;
  521.             Table[i]->String    = &Table[i]->Extra;
  522.             Table[i]->Extra        = i;
  523.             Table[i]->Len        = 1;
  524.         }
  525.         else
  526.             Success = FALSE;
  527.     }
  528.  
  529.     if(!Success)
  530.     {
  531.         for(i = 0 ; i < 256 ; i++)
  532.         {
  533.             FreeVecPooled(Table[i]);
  534.             Table[i] = NULL;
  535.         }
  536.     }
  537.  
  538.     return(Success);
  539. }
  540.  
  541.     /* IsStandardTable(struct TranslationEntry **Table):
  542.      *
  543.      *    Checks a translation table to see if it contains
  544.      *    standard data.
  545.      */
  546.  
  547. BOOL
  548. IsStandardTable(struct TranslationEntry **Table)
  549. {
  550.     LONG i;
  551.  
  552.     for(i = 0 ; i < 256 ; i++)
  553.     {
  554.         if(Table[i])
  555.         {
  556.             if(Table[i]->Type != TRANSLATE_SINGLE || Table[i]->Len != 1 || Table[i]->String[0] != i)
  557.                 return(FALSE);
  558.         }
  559.         else
  560.             return(FALSE);
  561.     }
  562.  
  563.     return(TRUE);
  564. }
  565.  
  566.     /* TranslateBack(STRPTR From,LONG Len,STRPTR To):
  567.      *
  568.      *    Translate a precompiled translation string
  569.      *    back.
  570.      */
  571.  
  572. VOID
  573. TranslateBack(STRPTR From,LONG Len,STRPTR To,LONG ToLen)
  574. {
  575.     STATIC BYTE TypeTable[256] =
  576.     {
  577.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 ,'b','t','n', 1 ,'f','r', 1 , 1,
  578.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 , 1 , 1 , 1 ,'e', 1 , 1 , 1 , 1,
  579.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  580.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  581.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  582.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 ,'\\',2 , 2 , 2,
  583.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  584.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0,
  585.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  586.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  587.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2,
  588.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  589.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  590.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  591.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  592.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
  593.     };
  594.  
  595.     STRPTR Buffer;
  596.     LONG i,j,BufLen;
  597.  
  598.     for(i = j = 0 ; i < Len ; i++)
  599.     {
  600.         switch(TypeTable[From[i]])
  601.         {
  602.             case 0:
  603.  
  604.                 Buffer = CodeToName(From[i]);
  605.  
  606.                 BufLen = strlen(Buffer);
  607.  
  608.                 if(j + 2 + BufLen >= ToLen)
  609.                     break;
  610.  
  611.                 To[j++] = '\\';
  612.                 To[j++] = '*';
  613.  
  614.                 CopyMem(Buffer,&To[j],BufLen);
  615.  
  616.                 j += BufLen;
  617.  
  618.                 break;
  619.  
  620.             case 1:
  621.  
  622.                 if(j + 2 >= ToLen)
  623.                     break;
  624.  
  625.                 To[j++] = '^';
  626.                 To[j++] = From[i] + '@';
  627.                 break;
  628.  
  629.             case 2:
  630.  
  631.                 if(j + 1 >= ToLen)
  632.                     break;
  633.  
  634.                 To[j++] = From[i];
  635.                 break;
  636.  
  637.             default:
  638.  
  639.                 if(j + 2 >= ToLen)
  640.                     break;
  641.  
  642.                 To[j++] = '\\';
  643.                 To[j++] = TypeTable[From[i]];
  644.                 break;
  645.         }
  646.     }
  647.  
  648.     To[j] = 0;
  649. }
  650.  
  651.     /* SaveTranslationTables():
  652.      *
  653.      *    Save a character translation table to a file.
  654.      */
  655.  
  656. BOOL
  657. SaveTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  658. {
  659.     LONG Error,i;
  660.     BOOL DoIt;
  661.  
  662.     DoIt = FALSE;
  663.  
  664.     for(i = 0 ; !DoIt && i < 256 ; i++)
  665.     {
  666.         if(SendTable[i] || ReceiveTable[i])
  667.             DoIt = TRUE;
  668.     }
  669.  
  670.     Error = 0;
  671.  
  672.     if(DoIt)
  673.     {
  674.         struct IFFHandle *Handle;
  675.         UBYTE MasterTable[256];
  676.  
  677.         for(i = 0 ; i < 256 ; i++)
  678.         {
  679.             if(SendTable[i])
  680.             {
  681.                 if(SendTable[i]->Type == TRANSLATE_SINGLE && SendTable[i]->Len == 1 && SendTable[i]->String[0] == i)
  682.                     MasterTable[i] = TRANSLATION_VERBATIM;
  683.                 else
  684.                     MasterTable[i] = TRANSLATION_OTHER;
  685.             }
  686.             else
  687.                 MasterTable[i] = TRANSLATION_IGNORE;
  688.  
  689.             if(ReceiveTable[i])
  690.             {
  691.                 if(ReceiveTable[i]->Type == TRANSLATE_SINGLE && ReceiveTable[i]->Len == 1 && ReceiveTable[i]->String[0] == i)
  692.                     MasterTable[i] |= TRANSLATION_VERBATIM << 4;
  693.                 else
  694.                     MasterTable[i] |= TRANSLATION_OTHER << 4;
  695.             }
  696.             else
  697.                 MasterTable[i] |= TRANSLATION_IGNORE << 4;
  698.         }
  699.  
  700.         if(!(Handle = OpenIFFStream(Name,MODE_NEWFILE)))
  701.             Error = IoErr();
  702.         else
  703.         {
  704.             if(!(Error = PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN)))
  705.             {
  706.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  707.                 {
  708.                     struct TermInfo TermInfo;
  709.  
  710.                     TermInfo.Version    = CONFIG_FILE_VERSION;
  711.                     TermInfo.Revision    = CONFIG_FILE_REVISION;
  712.  
  713.                     Error = AddIFFChunkBytes(Handle,ID_VERS,&TermInfo,sizeof(TermInfo));
  714.  
  715.                     if(!Error)
  716.                         Error = AddIFFChunkBytes(Handle,ID_TRNS,MasterTable,256);
  717.  
  718.                     if(!Error)
  719.                         Error = PopChunk(Handle);
  720.                 }
  721.  
  722.                 if(!Error)
  723.                 {
  724.                     struct TranslationHeader Header;
  725.  
  726.                     for(i = 0 ; !Error && i < 256 ; i++)
  727.                     {
  728.                         Header.Code    = i;
  729.                         Header.Pad    = 0;
  730.  
  731.                         if(SendTable[i] && (MasterTable[i] & 0xF) == TRANSLATION_OTHER)
  732.                         {
  733.                             Header.Type    = SendTable[i]->Type;
  734.                             Header.Len    = SendTable[i]->Len;
  735.  
  736.                             if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  737.                             {
  738.                                 Error = AddIFFChunkBytes(Handle,ID_SEND,&Header,sizeof(Header));
  739.  
  740.                                 if(!Error)
  741.                                     Error = AddIFFChunkBytes(Handle,ID_CHRS,SendTable[i]->String,SendTable[i]->Len);
  742.  
  743.                                 if(!Error)
  744.                                     Error = PopChunk(Handle);
  745.                             }
  746.                         }
  747.  
  748.                         if(ReceiveTable[i] && (MasterTable[i] >> 4) == TRANSLATION_OTHER)
  749.                         {
  750.                             Header.Type    = ReceiveTable[i]->Type;
  751.                             Header.Len    = ReceiveTable[i]->Len;
  752.  
  753.                             if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  754.                             {
  755.                                 Error = AddIFFChunkBytes(Handle,ID_RECV,&Header,sizeof(Header));
  756.  
  757.                                 if(!Error)
  758.                                     Error = AddIFFChunkBytes(Handle,ID_CHRS,ReceiveTable[i]->String,ReceiveTable[i]->Len);
  759.  
  760.                                 if(!Error)
  761.                                     Error = PopChunk(Handle);
  762.                             }
  763.                         }
  764.                     }
  765.                 }
  766.  
  767.                 if(!Error)
  768.                     Error = PopChunk(Handle);
  769.             }
  770.  
  771.             CloseIFFStream(Handle);
  772.         }
  773.     }
  774.  
  775.     if(Error)
  776.     {
  777.         SetIoErr(Error);
  778.         return(FALSE);
  779.     }
  780.     else
  781.         return(TRUE);
  782. }
  783.  
  784.     /* LoadTranslationTables():
  785.      *
  786.      *    Load a translation table from a file.
  787.      */
  788.  
  789. BOOL
  790. LoadTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  791. {
  792.     STATIC ULONG Stops[5 * 2] =
  793.     {
  794.         ID_TERM,    ID_VERS,
  795.         ID_TERM,    ID_TRNS,
  796.         ID_TERM,    ID_SEND,
  797.         ID_TERM,    ID_RECV,
  798.         ID_TERM,    ID_CHRS
  799.     };
  800.  
  801.     struct IFFHandle *Handle;
  802.     UBYTE MasterTable[256];
  803.     BOOL GotMasterTable;
  804.     BOOL Success;
  805.     LONG Error;
  806.     LONG i;
  807.  
  808.     GotMasterTable = FALSE;
  809.     Success = FALSE;
  810.  
  811.     if(Handle = OpenIFFStream(Name,MODE_OLDFILE))
  812.     {
  813.         if(!(Error = StopChunks(Handle,(LONG *)Stops,5)))
  814.         {
  815.             struct TranslationHeader Header;
  816.             struct ContextNode *Chunk;
  817.             struct TermInfo TermInfo;
  818.             LONG LastType;
  819.  
  820.             LastType = TYPE_NONE;
  821.             Success = TRUE;
  822.  
  823.             while(Success && !ParseIFF(Handle,IFFPARSE_SCAN))
  824.             {
  825.                 Chunk = CurrentChunk(Handle);
  826.  
  827.                 switch(Chunk->cn_ID)
  828.                 {
  829.                     case ID_VERS:
  830.  
  831.                         if(ReadIFFBytes(Handle,&TermInfo,sizeof(struct TermInfo)))
  832.                         {
  833.                             if(TermInfo.Version > CONFIG_FILE_VERSION || (TermInfo.Version == CONFIG_FILE_VERSION && TermInfo.Revision > CONFIG_FILE_REVISION))
  834.                             {
  835.                                 Error = ERR_OUTDATED;
  836.  
  837.                                 Success = FALSE;
  838.                             }
  839.                         }
  840.                         else
  841.                         {
  842.                             Error = IoErr();
  843.  
  844.                             Success = FALSE;
  845.                         }
  846.  
  847.                         break;
  848.  
  849.                     case ID_TRNS:
  850.  
  851.                         if(ReadIFFBytes(Handle,MasterTable,256))
  852.                             GotMasterTable = TRUE;
  853.                         else
  854.                         {
  855.                             Error = IoErr();
  856.  
  857.                             Success = FALSE;
  858.                         }
  859.  
  860.                         break;
  861.  
  862.                     case ID_SEND:
  863.  
  864.                         if(LastType != TYPE_NONE)
  865.                             Success = FALSE;
  866.                         else
  867.                         {
  868.                             if(!ReadIFFBytes(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk->cn_Size)))
  869.                             {
  870.                                 Error = IoErr();
  871.  
  872.                                 Success = FALSE;
  873.                             }
  874.                             else
  875.                                 LastType = TYPE_SEND;
  876.                         }
  877.  
  878.                         break;
  879.  
  880.                     case ID_RECV:
  881.  
  882.                         if(LastType != TYPE_NONE)
  883.                         {
  884.                             Error = IFFERR_MANGLED;
  885.  
  886.                             Success = FALSE;
  887.                         }
  888.                         else
  889.                         {
  890.                             if(!ReadIFFBytes(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk->cn_Size)))
  891.                             {
  892.                                 Success = FALSE;
  893.  
  894.                                 Error = IoErr();
  895.                             }
  896.                             else
  897.                                 LastType = TYPE_RECEIVE;
  898.                         }
  899.  
  900.                         break;
  901.  
  902.                     case ID_CHRS:
  903.  
  904.                         if(LastType == TYPE_NONE)
  905.                         {
  906.                             Error = IFFERR_MANGLED;
  907.  
  908.                             Success = FALSE;
  909.                         }
  910.                         else
  911.                         {
  912.                             UBYTE LocalBuffer[256];
  913.  
  914.                             if(ReadIFFBytes(Handle,LocalBuffer,Header.Len))
  915.                             {
  916.                                 struct TranslationEntry *Entry;
  917.  
  918.                                 if(Header.Type == TRANSLATE_SINGLE)
  919.                                 {
  920.                                     if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  921.                                     {
  922.                                         Entry->String    = &Entry->Extra;
  923.                                         Entry->Extra    = LocalBuffer[0];
  924.                                     }
  925.                                 }
  926.                                 else
  927.                                 {
  928.                                     if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Header.Len + 1,MEMF_ANY|MEMF_CLEAR))
  929.                                     {
  930.                                         Entry->String = (STRPTR)(Entry + 1);
  931.  
  932.                                         CopyMem(LocalBuffer,Entry->String,Header.Len);
  933.                                     }
  934.                                 }
  935.  
  936.                                 if(Entry)
  937.                                 {
  938.                                     Entry->Type    = Header.Type;
  939.                                     Entry->Len    = Header.Len;
  940.  
  941.                                     if(LastType == TYPE_SEND)
  942.                                         SendTable[Header.Code] = Entry;
  943.                                     else
  944.                                         ReceiveTable[Header.Code] = Entry;
  945.  
  946.                                     LastType = TYPE_NONE;
  947.                                 }
  948.                                 else
  949.                                 {
  950.                                     Error = ERROR_NO_FREE_STORE;
  951.  
  952.                                     Success = FALSE;
  953.                                 }
  954.                             }
  955.                             else
  956.                             {
  957.                                 Error = IoErr();
  958.  
  959.                                 Success = FALSE;
  960.                             }
  961.                         }
  962.  
  963.                         break;
  964.                 }
  965.             }
  966.         }
  967.  
  968.         CloseIFFStream(Handle);
  969.     }
  970.     else
  971.         Error = IoErr();
  972.  
  973.     if(Success && GotMasterTable)
  974.     {
  975.         struct TranslationEntry *Entry;
  976.  
  977.         for(i = 0 ; i < 256 ; i++)
  978.         {
  979.             if((MasterTable[i] & 0xF) == TRANSLATION_VERBATIM)
  980.             {
  981.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  982.                 {
  983.                     Entry->Type        = TRANSLATE_SINGLE;
  984.                     Entry->String    = &Entry->Extra;
  985.                     Entry->Extra    = i;
  986.                     Entry->Len        = 1;
  987.  
  988.                     SendTable[i] = Entry;
  989.                 }
  990.                 else
  991.                 {
  992.                     Error = ERROR_NO_FREE_STORE;
  993.  
  994.                     Success = FALSE;
  995.  
  996.                     break;
  997.                 }
  998.             }
  999.  
  1000.             if((MasterTable[i] >> 4) == TRANSLATION_VERBATIM)
  1001.             {
  1002.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1003.                 {
  1004.                     Entry->Type        = TRANSLATE_SINGLE;
  1005.                     Entry->String    = &Entry->Extra;
  1006.                     Entry->Extra    = i;
  1007.                     Entry->Len        = 1;
  1008.  
  1009.                     ReceiveTable[i] = Entry;
  1010.                 }
  1011.                 else
  1012.                 {
  1013.                     Error = ERROR_NO_FREE_STORE;
  1014.  
  1015.                     Success = FALSE;
  1016.  
  1017.                     break;
  1018.                 }
  1019.             }
  1020.         }
  1021.     }
  1022.  
  1023.     if(!Success)
  1024.     {
  1025.         for(i = 0 ; i < 256 ; i++)
  1026.         {
  1027.             if(SendTable[i])
  1028.             {
  1029.                 FreeTranslationEntry(SendTable[i]);
  1030.  
  1031.                 SendTable[i] = NULL;
  1032.             }
  1033.  
  1034.             if(ReceiveTable[i])
  1035.             {
  1036.                 FreeTranslationEntry(ReceiveTable[i]);
  1037.  
  1038.                 ReceiveTable[i] = NULL;
  1039.             }
  1040.         }
  1041.     }
  1042.  
  1043.     if(Error)
  1044.         SetIoErr(Error);
  1045.  
  1046.     return(Success);
  1047. }
  1048.  
  1049.     /* LoadDefaultTranslationTables(STRPTR FileName):
  1050.      *
  1051.      *    Load the default character translation file.
  1052.      */
  1053.  
  1054. BOOL
  1055. LoadDefaultTranslationTables(STRPTR FileName)
  1056. {
  1057.     BOOL Success;
  1058.  
  1059.     Success = FALSE;
  1060.  
  1061.     if(SendTable = AllocTranslationTable())
  1062.     {
  1063.         if(ReceiveTable = AllocTranslationTable())
  1064.         {
  1065.             BOOL ReleaseIt;
  1066.  
  1067.             if(LoadTranslationTables(FileName,SendTable,ReceiveTable))
  1068.             {
  1069.                 ReleaseIt = (BOOL)(IsStandardTable(SendTable) && IsStandardTable(ReceiveTable));
  1070.  
  1071.                 Success = TRUE;
  1072.             }
  1073.             else
  1074.                 ReleaseIt = TRUE;
  1075.  
  1076.             if(ReleaseIt)
  1077.             {
  1078.                 FreeTranslationTable(SendTable);
  1079.                 SendTable = NULL;
  1080.  
  1081.                 FreeTranslationTable(ReceiveTable);
  1082.                 ReceiveTable = NULL;
  1083.             }
  1084.         }
  1085.         else
  1086.         {
  1087.             FreeTranslationTable(SendTable);
  1088.             SendTable = NULL;
  1089.         }
  1090.     }
  1091.  
  1092.     return(Success);
  1093. }
  1094.